package com.media.photocamera.activity

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Log
import android.util.Rational
import android.util.Size
import android.view.*
import android.view.View.OnTouchListener
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.camera.core.*
import androidx.camera.core.ImageCapture.OnImageCapturedCallback
import androidx.camera.core.impl.utils.executor.CameraXExecutors
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.media.photocamera.R
import com.media.photocamera.utils.CameraConstans
import com.media.photocamera.utils.CameraFileUtils
import top.zibin.luban.Luban
import java.io.File
import java.util.concurrent.ExecutionException

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@SuppressLint("RestrictedApi")
class CameraXFacePhotoActivity : com.media.photocamera.activity.BaseCameraXActivity(), View.OnClickListener {
    private var previewView: PreviewView? = null
    private var mPreview: Preview? = null
    private var mCamera: Camera? = null
    private var mImageCapture: ImageCapture? = null
    private var mCameraProvider: ProcessCameraProvider? = null
    private var isBack = true
    private var markView: com.media.photocamera.view.CutMarkView? = null
    private var preview_result: ImageView? = null

    //	重拍
    private var btn_recapture: ImageView? = null

    //确定
    private var btn_ok: ImageView? = null

    //	拍照
    private var btn_capture: ImageView? = null

    //	取消
    private var btn_cancel: TextView? = null

    //切换摄像头
    private var btn_change: ImageView? = null

    //开灯
    private var btn_night: ImageButton? = null
    private var filepath: String? = null
    private var isSaveToAlbum = 0
    private var limit = 0
    private var TAG = "CameraXFacePhotoActivity"

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camerax_facephoto)
        previewView = findViewById(R.id.previewView)
        markView = findViewById(R.id.markView)
        preview_result = findViewById(R.id.preview_result)
        btn_capture = findViewById(R.id.btn_capture)
        btn_recapture = findViewById(R.id.btn_recapture)
        btn_ok = findViewById(R.id.btn_ok)
        btn_cancel = findViewById(R.id.btn_cancel)
        btn_change = findViewById(R.id.btn_change)
        btn_night = findViewById(R.id.btn_night)
        btn_capture?.setOnClickListener(this)
        btn_recapture?.setOnClickListener(this)
        btn_ok?.setOnClickListener(this)
        btn_cancel?.setOnClickListener(this)
        btn_change?.setOnClickListener(this)
        btn_night?.setOnClickListener(this)
        btn_ok!!.visibility = View.GONE
        btn_recapture!!.visibility = View.GONE
        var scale = intent.getDoubleExtra(CameraConstans.FACEPHOTO_scale, 0.75)
        if (scale < 0.6) {
            scale = 0.6
        }
        val widthScale = intent.getDoubleExtra(CameraConstans.FACEPHOTO_widthScale, 0.8)
        isSaveToAlbum = intent.getIntExtra(CameraConstans.FACEPHOTO_isSaveToAlbum, 0)
        val isFront = intent.getIntExtra(CameraConstans.FACEPHOTO_isFront, 0)
        isBack = isFront != 1
        limit = intent.getIntExtra(CameraConstans.FACEPHOTO_limit, 1024)
        //        var light = intent.getIntExtra(Constans.FACEPHOTO_light, 1)
        previewView?.post(Runnable {
            val width = previewView!!.getWidth()
            val height = previewView!!.getHeight()
            val screamWidth = (width * widthScale).toInt()
            val targetHight = (screamWidth / scale).toInt()
            markView?.setMaskSize(screamWidth, targetHight, width, height)
            markView?.visibility = View.VISIBLE
        })
        //        int screamWidth = (int) (UiUtil.getScreamWidth(this) * 0.9);
//        int targetHight = (int) (screamWidth / (3.0 / 4.0));
//        markView.setMaskSize(screamWidth, targetHight, UiUtil.getScreamWidth(this), UiUtil.getScreamHeight(this));
        ensureCameraPermission()
        previewView?.setOnTouchListener(OnTouchListener { v, event ->
            val action = FocusMeteringAction.Builder(
                    previewView!!.getMeteringPointFactory()
                            .createPoint(event.x, event.y)
            ).build()
            try {
                showTapView(event.x.toInt(), event.y.toInt(), previewView!!)
                Log.d("Camera", "Focus camera")
                mCamera!!.cameraControl.startFocusAndMetering(action)
            } catch (e: Exception) {
                Log.e("Camera", "Error focus camera")
            }
            false
        })
    }


    override fun onClick(v: View) {
        if (v === btn_capture) {
            //	拍照
            ensureAudioStoragePermission(REQUEST_STORAGE)
        } else if (v === btn_recapture) {
            //	重拍
            filepath = null
            setButtomControlStatus(CAPTURED_IDEL)
        } else if (v === btn_ok) {
            //确定
            setResult(
                    Activity.RESULT_OK,
                    Intent().putExtra(CameraConstans.CALL_BACK_FACEPHOTO_CODE, filepath)
            )
            finish()
            if (isSaveToAlbum == 1) {
                CameraFileUtils.copyFile2Album(application, filepath, CameraConstans.IMAGEPATH)
            }
        } else if (v === btn_cancel) {
            //	取消
            finish()
            CameraFileUtils.deleteCacheFile(this.application,filepath)
        } else if (v === btn_change) {
            //切换摄像头
            if (mCameraProvider != null) {
                isBack = !isBack
                bindPreview(mCameraProvider!!, previewView!!)
            }
        } else if (v === btn_night) {
            //开灯
            onChangeNight()
        }
    }

    private fun setButtomControlStatus(isCapture: Int) {
        if (CAPTURED_IDEL == isCapture) {
            //正在拍照
            btn_cancel!!.visibility = View.VISIBLE
            btn_capture!!.visibility = View.VISIBLE
            btn_ok!!.visibility = View.GONE
            btn_recapture!!.visibility = View.GONE
            preview_result!!.visibility = View.GONE
            if (!isBack) {
                btn_night?.visibility = View.GONE
            } else {
                btn_night?.visibility = View.VISIBLE
            }
            btn_change?.visibility = View.VISIBLE
            previewView?.visibility = View.VISIBLE
            markView?.visibility = View.VISIBLE
        } else if (CAPTURED_SURE == isCapture) {
            //拍照成功
            btn_cancel!!.visibility = View.GONE
            btn_capture!!.visibility = View.GONE
            btn_ok!!.visibility = View.VISIBLE
            btn_recapture!!.visibility = View.VISIBLE
            btn_night?.visibility = View.GONE
            btn_change?.visibility = View.GONE
            previewView?.visibility = View.GONE
            markView?.visibility = View.GONE
        } else if (CAPTURED_SAVEING == isCapture) {
            //拍照等待 裁剪回调
            btn_cancel!!.visibility = View.GONE
            btn_capture!!.visibility = View.GONE
            btn_ok!!.visibility = View.GONE
            btn_recapture!!.visibility = View.GONE
            btn_night?.visibility = View.GONE
            btn_change?.visibility = View.GONE
        }
    }

    //灯光
    fun onChangeNight() {
        val flashMode = mImageCapture!!.flashMode
        if (flashMode == ImageCapture.FLASH_MODE_ON) {
            mImageCapture!!.flashMode = ImageCapture.FLASH_MODE_AUTO
            btn_night!!.setImageResource(R.drawable.camerax_flash_auto)
        } else if (flashMode == ImageCapture.FLASH_MODE_OFF) {
            mImageCapture!!.flashMode = ImageCapture.FLASH_MODE_ON
            btn_night!!.setImageResource(R.drawable.camerax_flash_on)
        } else if (flashMode == ImageCapture.FLASH_MODE_AUTO) {
            mImageCapture!!.flashMode = ImageCapture.FLASH_MODE_OFF
            btn_night!!.setImageResource(R.drawable.camerax_flash_off)
        }
    }

    private fun bindPreview(
            cameraProvider: ProcessCameraProvider,
            previewView: PreviewView) {
        val cameraSelector =
                if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA
        val metrics = DisplayMetrics().also {
            previewView.display.getRealMetrics(it)}
        val ration = 1f
        val applyWidthPixels = (metrics.widthPixels * ration).toInt()
        val applyHeightPixel = (metrics.heightPixels * ration).toInt()
        val resolution = Size(applyWidthPixels, applyHeightPixel)
        val rotation = (getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation
        // Preview用例配置，这里经过了大量的测试得到的最兼容的配置
        val previewBuilder = Preview.Builder()
                .setMaxResolution(resolution)
//            .setTargetAspectRatio(screenAspectRatio)
                .setTargetResolution(resolution)
                .setTargetRotation(rotation);

        val imageCaptureBuilder = ImageCapture.Builder()
                .setMaxResolution(resolution)
                // 尽量用screen AspectRation，fix SM-J600G 预览拉伸
                // .setTargetAspectRatio(applyWidthPixels / applyHeightPixel)
                //设置默认比例，目前有RATIO_4_3和RATIO_16_9两种
                .setTargetAspectRatio(AspectRatio.RATIO_16_9)
                .setTargetRotation(rotation)
//                .setTargetRotation(previewView.display.rotation)
//                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY);

        setPreviewExtender(previewBuilder, cameraSelector)
        setCaptureExtender(imageCaptureBuilder, cameraSelector)

        mPreview = previewBuilder.build()
        mImageCapture =  imageCaptureBuilder.build()

        // 配置此处的原因是 预览界面与相机捕获界面一致
        mImageCapture?.setCropAspectRatio(Rational(applyWidthPixels, applyHeightPixel))
        //  mImageCapture.setViewPortCropRect(new Rect(100,100,500,1000));

        cameraProvider.unbindAll()

        mCamera = cameraProvider.bindToLifecycle(
                this, cameraSelector,
                mPreview, mImageCapture)
        mPreview!!.setSurfaceProvider(previewView.surfaceProvider)
    }

    /**
     * 权限
     *
     * @param requestId
     */
    private fun ensureAudioStoragePermission(requestId: Int) {
        if (requestId == REQUEST_STORAGE) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED
            ) {
                ActivityCompat.requestPermissions(
                        this,
                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                        requestId
                )
                return
            }
            //拍照
            takenPictureInternal()
        }
    }

    @SuppressLint("RestrictedApi")
    private fun takenPictureInternal() {
        var start=System.currentTimeMillis();
        if (mImageCapture != null) {
            filepath =  CameraFileUtils.getImageSaveRootPath(this.application)+System.currentTimeMillis()+".jpeg";
            setButtomControlStatus(CAPTURED_SAVEING)
            mImageCapture!!.takePicture(CameraXExecutors.mainThreadExecutor(),
                    object : OnImageCapturedCallback() {
                        @SuppressLint("UnsafeExperimentalUsageError")
                        override fun onCaptureSuccess(image: ImageProxy) {
                            super.onCaptureSuccess(image)
                            Log.d("Camera", "onCaptureSuccess " + Thread.currentThread().id)
                            Thread(Runnable {
                                val byteBuffer = image.planes[0].buffer
                                val data = ByteArray(byteBuffer.remaining())
                                byteBuffer[data]
                                var bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
                                bitmap = rotateBitmap(isBack, bitmap)
                                bitmap = cutFaceImage(bitmap)
                                runOnUiThread(Runnable {
                                    preview_result?.setImageBitmap(bitmap)
                                    preview_result?.setVisibility(View.VISIBLE)
                                    setButtomControlStatus(CAPTURED_SURE)
                                })
                                CameraFileUtils.savePictureByBitmap(filepath, bitmap)
                                var file= File(filepath)
                                Log.d(TAG, "文件压缩前：" + " 大小：" + file.length() + "   " + CameraFileUtils.getReadableFileSize(file.length()) + " 路径：" + file.getAbsolutePath())
                                if (file.length() > limit * 1024) {
                                    val startZipTime = System.currentTimeMillis()
                                    val file1 = Luban.with(application)[file.getAbsolutePath()]
                                    val endZipTime = System.currentTimeMillis()
                                    Log.d(TAG, "文件压缩后：" + " 大小：" + CameraFileUtils.getReadableFileSize(file1.length()) + " 用时：" + (endZipTime - startZipTime) + " 路径：" + file1.absolutePath)
                                    filepath = file1.absolutePath
                                }
                                // 拿到拍照的数据
                                //Image image = reader.acquireNextImage();
                                // 需要在这个事件监听里面调用close
                                image.close();
                                Log.d(TAG, "  用时：" + (System.currentTimeMillis() - start) )

                            }).start()
                        }

                        override fun onError(exception: ImageCaptureException) {
                            Log.d("Camera", "onError:" + exception.imageCaptureError)
                            setButtomControlStatus(CAPTURED_IDEL)
                        }
                    })
        }
    }

    private fun cutFaceImage(bitmap1: Bitmap): Bitmap {
        try {
            if (markView!!.maskWidth > 0 && markView!!.maskHeight > 0) {
                val targety =
                        (bitmap1.height * markView!!.maskHeight / markView!!.height.toDouble()).toInt()
                val targetx =
                        (markView!!.maskWidth * targety / markView!!.maskHeight.toDouble()).toInt()
                val y = (bitmap1.height - targety) / 2
                val x = (bitmap1.width - targetx) / 2
                return  Bitmap.createBitmap(bitmap1, x, y, targetx, targety)
            }
        } catch (e: Exception) {
        }
        return bitmap1
    }


    private fun ensureCameraPermission() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.CAMERA),
                    REQUEST_CAMERA
            )
            return
        }
        setupCamera(previewView)
    }

    private fun setupCamera(previewView: PreviewView?) {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener(Runnable {
            try {
                mCameraProvider = cameraProviderFuture.get()
                bindPreview(mCameraProvider!!, previewView!!)
            } catch (e: ExecutionException) {
                e.printStackTrace()
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }
        }, ContextCompat.getMainExecutor(this))
    }

    override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<String>,
            grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        for (result in grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                return
            }
        }
        when (requestCode) {
            REQUEST_CAMERA -> setupCamera(previewView)
            REQUEST_STORAGE -> takenPictureInternal()
            else -> {
            }
        }
    }


    override fun onDestroy() {
        super.onDestroy()
        mCameraProvider?.shutdown()
    }


}